package com.zl.basic.CommonUtil;

import org.apache.commons.lang.ArrayUtils;
import org.junit.Assert;

import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;


/**
 * User: zl email:c3tc3tc3t@126.com Date: 14-2-13 Time: 下午4:06
 */
// 测试工具比较类
public class TestUtil {
  /**
   * 根据类型测试两个对象是否相同
   * 
   * @param expected 期望的对象
   * @param actual 实际的对象
   * @param clz 对象类型
   * @param excludeProps 需要排除的属性,不比较的属性
   * @throws InvocationTargetException
   * @throws IllegalAccessException
   * @throws IllegalArgumentException
   */
  public static void assertObjByClz(Object expected, Object actual, Class clz, String[] excludeProps)
      throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
    Assert.assertNotNull(expected);
    Method[] ms = clz.getDeclaredMethods();
    for (Method m : ms) {
      String name = m.getName();
      if (name.startsWith("get")) {
        if (isExclude(name, excludeProps)) {
          Object e = m.invoke(expected);
          Object a = m.invoke(actual);
          Assert.assertEquals(e, a);
        }
      }
    }
  }

  /**
   * 不需要排除对象的属性。所有属性都比较
   * 
   * @param expected
   * @param actual
   * @param clz
   * @throws IllegalArgumentException
   * @throws IllegalAccessException
   * @throws InvocationTargetException
   */
  public static void assertObjByClz(Object expected, Object actual, Class clz)
      throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
    assertObjByClz(expected, actual, clz, null);
  }

  public static void assertListByClz(List<?> expecteds, List<?> actuals, Class clz,
      String[] excludeProps) throws IllegalArgumentException, IllegalAccessException,
      InvocationTargetException {
    Assert.assertNotNull(expecteds);
    Assert.assertEquals(expecteds.size(), actuals.size());
    for (int i = 0; i < expecteds.size(); i++) {
      Object e = expecteds.get(i);
      Object a = actuals.get(i);
      assertObjByClz(e, a, clz, excludeProps);
    }
  }

  public static void assertListByClz(Set<?> expecteds, Set<?> actuals, Class clz,
      String[] excludeProps) throws IllegalArgumentException, IllegalAccessException,
      InvocationTargetException {
    Assert.assertNotNull(expecteds);
    Assert.assertEquals(expecteds.size(), actuals.size());
    ArrayList<Object> el = new ArrayList<>(expecteds);
    ArrayList<Object> al = new ArrayList<>(actuals);
    for (int i = 0; i < el.size(); i++) {
      Object e = el.get(i);
      Object a = al.get(i);
      assertObjByClz(e, a, clz, excludeProps);
    }
  }

  /**
   * 判断某个属性是是否在排除属性数组中
   * 
   * @param name
   * @param excludeProps
   * @return
   */
  private static boolean isExclude(String name, String[] excludeProps) {
    // 排除属性为空，对象中的属性全都比较
    if (excludeProps == null) return true;

    String pn = name.substring(3);
    pn = pn.substring(0, 1).toLowerCase() + pn.substring(1);

    // 属性存在排除比较列表里面不比较，返回flase
    if (ArrayUtils.contains(excludeProps, pn)) {
      return false;
    } else {
      return true;
    }


  }
}
